设计模式——工厂模式

由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 四人合著出版的 Design Patterns - Elements of Reusable Object-Oriented Software(设计模式 - 可复用的面向对象软件元素),该书首次提到了软件开发中设计模式的概念。

四位作者合称 GOF(四人帮,全拼 Gang of Four)。他们所提出的设计模式主要是基于以下的面向对象设计原则。

  • 对接口编程而不是对实现编程。
  • 优先使用对象组合而不是继承。

GOF对工厂模式的定义:在基类中定义创建对象的一个接口,让子类决定实例化哪个类。工厂方法让一个类的实例化延迟到子类中进行。

1.简单工厂模式

1.1 开闭原则(Open Close Principle)

开闭原则的意思是:对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类。

1.2 简单工厂介绍

简单工厂模式属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式在实际中的应用相对于其他2个工厂模式用的还是相对少得多,因为它只适应很多简单的情况,而且它违背了开放-封闭原则

适用于:

(1)需要创建的对象较少。

(2)客户端不关心对象的创建过程。

1.3 简单工厂的优点/缺点

  • 优点:简单工厂模式能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。明确区分了各自的职责和权力,有利于整个软件体系结构的优化。
  • 缺点:很明显工厂类集中了所有实例的创建逻辑,容易违反GRASPR的高内聚的责任分配原则

1.4 简单工厂实例

创建一个可以绘制圆形,正方形,三角形的绘图工具,每个图形都会有一个draw()方法用于绘图。

(1)创建Shape接口

1
2
3
public interface Shape {
void draw();
}

(2)创建实现该接口的具体图形类

圆形

1
2
3
4
5
6
7
8
9
public class Circle implements Shape {
public Circle() {
System.out.println("Circle");
}
@Override
public void draw() {
System.out.println("Draw Circle");
}
}

长方形

1
2
3
4
5
6
7
8
9
public class Rectangle implements Shape {
public Rectangle() {
System.out.println("Rectangle");
}
@Override
public void draw() {
System.out.println("Draw Rectangle");
}
}

正方形

1
2
3
4
5
6
7
8
9
10
public class Square implements Shape {
public Square() {
System.out.println("Square");
}

@Override
public void draw() {
System.out.println("Draw Square");
}
}

(3)创建工厂类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class ShapeFactory {

// 使用 getShape 方法获取形状类型的对象
public static Shape getShape(String shapeType) {
if (shapeType == null) {
return null;
}
if (shapeType.equalsIgnoreCase("CIRCLE")) {
return new Circle();
} else if (shapeType.equalsIgnoreCase("RECTANGLE")) {
return new Rectangle();
} else if (shapeType.equalsIgnoreCase("SQUARE")) {
return new Square();
}
return null;
}
}

(4)测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Test {

public static void main(String[] args) {

// 获取 Circle 的对象,并调用它的 draw 方法
Shape circle = ShapeFactory.getShape("CIRCLE");
circle.draw();

// 获取 Rectangle 的对象,并调用它的 draw 方法
Shape rectangle = ShapeFactory.getShape("RECTANGLE");
rectangle.draw();

// 获取 Square 的对象,并调用它的 draw 方法
Shape square = ShapeFactory.getShape("SQUARE");
square.draw();
}
}

如果我们新增产品类的,就需要修改工厂类中的getShape()方法,这很明显不符合 开放-封闭原则

2.工厂方法模式

2.1 工厂方法介绍

工厂方法模式在工厂模式家族中是用的最多的模式,工厂方法模式是简单工厂的仅一步深化, 在工厂方法模式中,我们不再提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂。也就是说 每个对象都有一个与之对应的工厂

应用实例: 1、您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。 2、Hibernate 换数据库只需换方言和驱动就可以。

适用于:

(1)一个类不知道它所需要的对象的类:在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;客户端需要知道创建具体产品的工厂类。
(2)一个类通过其子类来指定创建哪个对象:在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏
(3)将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无需关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。

2.2 工厂方法优点/缺点

优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。 2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 3、屏蔽产品的具体实现,调用者只关心产品的接口。

缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

2.3 工厂方法实例

之前例子中的图形接口以及相关图像实现类不变。我们只需要增加一个工厂接口以及实现这个接口的工厂类即可。

(1)增加一个工厂接口:

1
2
3
public interface Factory {
public Shape getShape();
}

(2)增加相关工厂类:

圆形工厂类

1
2
3
4
5
6
7
8
9
public class CircleFactory implements Factory {

@Override
public Shape getShape() {
// TODO Auto-generated method stub
return new Circle();
}

}

长方形工厂类

public class RectangleFactory implements Factory{

    @Override
    public Shape getShape() {
        // TODO Auto-generated method stub
        return new Rectangle();
    }

}

圆形工厂类

1
2
3
4
5
6
7
8
9
public class SquareFactory implements Factory{

@Override
public Shape getShape() {
// TODO Auto-generated method stub
return new Square();
}

}

(3)测试:

1
2
3
4
5
6
7
8
9
public class Test {

public static void main(String[] args) {
Factory circlefactory = new CircleFactory();
Shape circle = circlefactory.getShape();
circle.draw();
}

}

3.参考资料

  1. https://blog.csdn.net/qq_34337272/article/details/80472071
  2. https://www.cnblogs.com/toutou/p/4899388.html
  3. https://www.runoob.com/design-pattern/factory-pattern.html
0%